package com.gitee.hermer.engine.jars.app.sdk;

import java.lang.reflect.Method;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotatedElementUtils;

import com.gitee.hermer.boot.jee.commons.bean.utils.BeanLocator;
import com.gitee.hermer.boot.jee.commons.log.UtilsContext;
import com.gitee.hermer.boot.jee.commons.reflect.ClassUtils;
import com.gitee.hermer.boot.jee.commons.reflect.ReflectUtils;
import com.gitee.hermer.boot.jee.commons.utils.StringUtils;
import com.gitee.hermer.engine.jars.core.annotate.EngineComponent;
import com.gitee.hermer.engine.jars.app.sdk.proxy.ExecuteProxy;
import com.gitee.hermer.engine.jars.app.sdk.utils.ApplicationContextUtils;
import com.gitee.hermer.engine.jars.core.annotate.EngineAppJob;
import com.gitee.hermer.engine.jars.core.app.domain.EngineAppContext;
import com.gitee.hermer.engine.jars.core.app.domain.EngineAppMethodBean;
import com.gitee.hermer.engine.jars.core.domain.EngineConstant;
import com.gitee.hermer.engine.jars.core.eventbus.annotate.OnEvent;

public class EngineApplicationRefreshBeanEvent extends UtilsContext implements ApplicationListener<ContextRefreshedEvent>{

	@Autowired(required = false) 
	private EngineAppContext context;



	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if(event.getApplicationContext().getClassLoader() instanceof EngineAppClassLoader){
			
			ApplicationContextUtils.setApplicationContext(event.getApplicationContext());
			
			EngineAppClassLoader appClassLoader = (EngineAppClassLoader) event.getApplicationContext().getClassLoader();

			Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(EngineComponent.class);
			for (String beanName : beans.keySet()) {
				Object bean = beans.get(beanName);
				if(!ExecuteProxy.isProxyClass(bean)){
					try{
						Class clazz = ClassUtils.getTargetProxy(bean).getClass();
						Method[] methods = clazz.getMethods();
						for (Method method : methods) {
							if(method == null || EngineConstant.EXCLUSION_METHODS.contains(method.getName()))
								continue;
							if(context != null){
								if(method.getName().equals("locationReceive")){
									method.getAnnotations();
									System.out.println(1);
								}
								EngineAppJob job = AnnotatedElementUtils.getMergedAnnotation(method, EngineAppJob.class);
								if(job != null && StringUtils.isNotBlank(job.jobMethod())){
									context.registerJob(job.jobMethod(), new EngineAppMethodBean(appClassLoader.getCacheKey(),
											clazz,job,beanName,bean,method.getName(),job.jobVersion(),job.describe(),
											method,method.getGenericParameterTypes(),method.getParameterTypes(),method.getReturnType()));
								}
								OnEvent onevent = AnnotatedElementUtils.getMergedAnnotation(method, OnEvent.class);
								if(onevent != null && StringUtils.isNotBlank(onevent.eventName())){
									Object beanObject = BeanLocator.getBean(EngineConstant.CLASS_EVENT_BUS_REGISTER);
									EngineAppMethodBean methodBean = new EngineAppMethodBean(appClassLoader.getCacheKey(),clazz,onevent,
											beanName,bean,method.getName(),null,null,method,method.getGenericParameterTypes(),
											method.getParameterTypes(),method.getReturnType());
									Method register = EngineConstant.CLASS_EVENT_BUS_REGISTER.getDeclaredMethod(EngineConstant.BEAN_METHOD_NAME_REGISTER,
											String.class,EngineAppMethodBean.class);
									ReflectUtils.invoke(beanObject, new Object[]{onevent.eventName(),methodBean}, register);
								}

							}

						}
					}catch (Throwable e) {
						error(e.getMessage(),e);
					}
				}
			}
		}
	}

}
